package com.service;

import static com.def.GenericDef.BANK_IN;
import static com.def.GenericDef.BANK_OUT;
import static com.def.GenericDef.BOX_INVALIED;
import static com.def.GenericDef.EVT_WIP_BANK_IN;
import static com.def.GenericDef.EVT_WIP_BANK_OUT;
import static com.def.GenericDef.E_READ_NOT_FOUND;
import static com.def.GenericDef.E_RET_BOX;
import static com.def.GenericDef.E_XPWIPBANKT_INVALID_INPUT;
import static com.def.GenericDef.E_XPWIPBANKT_INVALIED_BOX;
import static com.def.GenericDef.E_XPWIPBANKT_INVALIED_BOX_BNK_FLG;
import static com.def.GenericDef.E_XPWIPBANKT_INVALIED_BOX_STAT;
import static com.def.GenericDef.PROC_WAIT;
import static com.def.GenericDef.RETURN_CODE_OK;
import static com.def.GenericDef.RETURN_CODE_SET_ERROR;
import static com.def.GenericDef.RETURN_CODE_UNKNOWN;
import static com.def.GenericDef.RETURN_MESG_OK;
import static com.def.GenericDef.TRX_OUT;
import static com.def.GenericDef.T_XPWIPBANK;
import static com.def.GenericDef._NORMAL;
import static com.def.GenericDef._SPACE;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.LockMode;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import com.dao.IRetBoxDao;
import com.dao.IRetPrdInfoDao;
import com.icim.service.ICIMBaseService;
import com.model.Ret_box;
import com.model.Ret_prd_info;
import com.rtnBean.NotFoundRtnBeen;
import com.tx.Xpwipbank.XpwipbankI;
import com.tx.Xpwipbank.XpwipbankIA;
import com.tx.Xpwipbank.XpwipbankO;
import com.util.GUIDGenerator;
import com.util.MqOpe;
import com.util.Util;

@Scope("prototype")
@Service("XpwipbankService")
public class XpwipbankService extends ICIMBaseService{
	private static Logger logger = Logger.getLogger(XpwipbankService.class);
	private static String TX_NAME = T_XPWIPBANK;

	private XpwipbankI inTrx;
	private XpwipbankO outTrx;
	private MqOpe mqOpe;

	private String gszMsgBuf = "";
	private Timestamp gEvtTimestamp;
	private Double gEvtTimeD;
	private String gEvtSeqID;

	@Autowired
	private IRetBoxDao retBoxDao;
	@Autowired
	private IRetPrdInfoDao retPrdInfoDao;

	public String subMainProc(String strInMsg) {
		Session session = retPrdInfoDao.getCrSession();

		long rtnCode = _NORMAL;
		String outMsg = null;
		gszMsgBuf = "";
		gEvtTimestamp = Util.getCurrentTimestamp();
		gEvtTimeD = Util.getDoubleTime();
		gEvtSeqID = GUIDGenerator.javaGUID();

		inTrx = new XpwipbankI();
		outTrx = new XpwipbankO();
		outTrx.setTrx_id(TX_NAME);
		outTrx.setType_id(TRX_OUT);
		outTrx.setRtn_code(String.valueOf(RETURN_CODE_SET_ERROR));
		mqOpe = new MqOpe();

		try {
			inTrx = (XpwipbankI) mqOpe.inStr2Obj(strInMsg, inTrx);
			logger.info("InTrx is " + strInMsg);

			rtnCode = subMainProc2(inTrx.getAction_flg().toCharArray()[0]);
			if (rtnCode != _NORMAL) {
				TransactionAspectSupport.currentTransactionStatus()
						.setRollbackOnly();
				outTrx.setRtn_code(String.valueOf(rtnCode));
				outTrx.setRtn_mesg(gszMsgBuf);
			} else {
				outTrx.setRtn_code(String.valueOf(RETURN_CODE_OK));
				outTrx.setRtn_mesg(RETURN_MESG_OK);
				session.flush();
			}
		} catch (Exception ex) {
			TransactionAspectSupport.currentTransactionStatus()
					.setRollbackOnly();
			outTrx.setRtn_mesg(ex.toString());
			outTrx.setRtn_code(RETURN_CODE_UNKNOWN);
			logger.error(Util.stackTraceToString(ex));
		} finally {
			outMsg = mqOpe.obj2Str(outTrx);
			return outMsg;
		}
	}

	private long subMainProc2(char actionType) {
		long lRc = _NORMAL;
		switch (actionType) {
		case 'O': {
			lRc = wipbankOut();
			break;
		}
		case 'I': {
			lRc = wipbankIn();
			break;
		}
		default: {
			gszMsgBuf = "Invalide type input: [" + actionType + "]";
			return E_XPWIPBANKT_INVALID_INPUT;
		}
		}

		return lRc;
	}

	/**
	 * Wip bank in
	 * 
	 * @return
	 */
	private long wipbankIn() {
		String box_id = inTrx.getBox_id();
		String bank_id = inTrx.getTool_id();
		Ret_box ret_box = new Ret_box();
		List<Ret_prd_info> ret_prd_infoList = new ArrayList<Ret_prd_info>();

		ret_box = retBoxDao.getWithLock(box_id, LockMode.UPGRADE);
		if (null == ret_box) {
			gszMsgBuf = new NotFoundRtnBeen(box_id, Ret_box.class).toString();
			return E_RET_BOX + E_READ_NOT_FOUND;
		}

		if (!ret_box.getBox_stat().equals(PROC_WAIT)) {
			gszMsgBuf = "箱子状态必须是[" + PROC_WAIT + "],当前状态为["
					+ ret_box.getBox_stat() + "]";
			return E_XPWIPBANKT_INVALIED_BOX_STAT;
		}

		if (!ret_box.getBnk_flg().equals(BANK_OUT)) {
			gszMsgBuf = "箱子已经在仓库中，请勿重复操作！";
			return E_XPWIPBANKT_INVALIED_BOX_BNK_FLG;
		}

		ret_prd_infoList = retPrdInfoDao.getShtListInfo(box_id);
		if (null != ret_prd_infoList) {
			for (Ret_prd_info prd : ret_prd_infoList) {
				prd.setEvt_cate(EVT_WIP_BANK_IN);
				prd.setEvt_usr(inTrx.getEvt_usr());
				prd.setEvt_timestamp(gEvtTimestamp);
				prd.setEvt_time_d(gEvtTimeD);
				prd.setEvt_seq_id(gEvtSeqID);

				prd.setBnk_flg(BANK_IN);
				prd.setPv_tool_id_fk(prd.getTool_id_fk());
				prd.setTool_id_fk(bank_id);

				retPrdInfoDao.update(prd);
			}
			ret_box.setBnk_flg(BANK_IN);
			ret_box.setEvt_cate(EVT_WIP_BANK_IN);
			ret_box.setTool_id_fk(bank_id);

			retBoxDao.update(ret_box);
		} else {
			gszMsgBuf = "箱子[" + box_id + "]中无玻璃！！！";
			return BOX_INVALIED;
		}

		return _NORMAL;
	}

	/**
	 * Wip bank out
	 * 
	 * @return
	 */
	private long wipbankOut() {
		List<XpwipbankIA> iary = new ArrayList<XpwipbankIA>();
		Integer box_cnt = inTrx.getBox_cnt();
		iary = inTrx.getIary();
		if (box_cnt > 0 && !iary.isEmpty()) {
			for (XpwipbankIA box_info : iary) {
				String box_id = box_info.getBox_id();

				Ret_box box = new Ret_box();
				List<Ret_prd_info> ret_prd_infoList = new ArrayList<Ret_prd_info>();
				box = retBoxDao.get(box_id);
				if (null == box) {
					gszMsgBuf = new NotFoundRtnBeen(box_id, Ret_box.class)
							.toString();
					return E_RET_BOX + E_READ_NOT_FOUND;
				}
				if (box.getBox_stat().equals(PROC_WAIT)
						&& box.getBnk_flg().equals(BANK_IN)) {
					ret_prd_infoList = retPrdInfoDao.getShtListInfo(box_id);
					if (null != ret_prd_infoList) {
						for (Ret_prd_info prd : ret_prd_infoList) {
							prd.setEvt_cate(EVT_WIP_BANK_OUT);
							prd.setEvt_usr(inTrx.getEvt_usr());
							prd.setEvt_timestamp(gEvtTimestamp);
							prd.setEvt_time_d(gEvtTimeD);
							prd.setEvt_seq_id(gEvtSeqID);

							prd.setTool_id_fk(prd.getPv_tool_id_fk());
							prd.setPv_tool_id_fk(_SPACE);
							prd.setBnk_flg(BANK_OUT);

							retPrdInfoDao.update(prd);
						}

						box.setEvt_cate(EVT_WIP_BANK_OUT);
						box.setEvt_usr(inTrx.getEvt_usr());
						box.setEvt_time_d(gEvtTimeD);
						box.setEvt_timestamp(gEvtTimestamp);
						box.setTool_id_fk(ret_prd_infoList.get(0)
								.getTool_id_fk());
						box.setBnk_flg(BANK_OUT);

						retBoxDao.update(box);
					} else {
						gszMsgBuf = "箱子[" + box_id + "]中无玻璃！！！";
						return BOX_INVALIED;
					}
				} else {
					gszMsgBuf = "箱子[" + box_id + "]状态为[" + box.getBox_stat()
							+ "]在库标示为[" + box.getBnk_flg() + "]，不属于在制仓。";
					return E_XPWIPBANKT_INVALIED_BOX;
				}
			}

		}

		return _NORMAL;
	}

}
